package com.jia.lightrailsystem

import android.util.Log
import com.blankj.utilcode.util.LogUtils
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import java.io.IOException
import java.net.Socket
import java.net.SocketException
import java.net.SocketTimeoutException

object SocketClient {
    // 配置常量
    private const val DEFAULT_SERVER_IP = "39.107.78.202"
    private const val DEFAULT_SERVER_PORT = 8888
    private const val BUFFER_SIZE = 1024 * 1024
    private const val HEARTBEAT_INTERVAL = 30000L       // 心跳间隔30秒
    private const val RECONNECT_DELAY = 15000L  // 固定15秒重连间隔
    private const val MAX_RECONNECT_ATTEMPTS = Int.MAX_VALUE  // 可选：如果需要无限重连
    private const val MAX_RECONNECT_INTERVAL = 30000L  // 最大重连间隔30秒
    private const val SOCKET_TIMEOUT = 10000L
    private const val MESSAGE_DELIMITER = "\n"

    // 状态变量
    private var serverIp = DEFAULT_SERVER_IP
    private var serverPort = DEFAULT_SERVER_PORT
    private var socket: Socket? = null
    private var isRunning = false
    private var isManualStop = false                   // 是否手动停止
    private var lastActivityTime = System.currentTimeMillis() // 最后活动时间戳
    private var reconnectAttempts = 0                  // 重连尝试次数

    // 协程管理
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    private val sendChannel = Channel<String>(Channel.UNLIMITED)
    private val receiveBuffer = StringBuilder()

    // 连接状态通知
    private val _connectionStatus = MutableStateFlow(false)
    val connectionStatus: StateFlow<Boolean> = _connectionStatus

    // 外部依赖
    var mainViewModel: MainVM? = null

    enum class PhotoStatus(val code: Int) {
        THREE_D_PHOTO(311), TAKE_PHOTO(331),
        TAKE_TWO_PHOTO(342), THREE_D_TWO_PHOTO(322),
        CODE_PRINTER(39)
    }

    /* ========== 公开方法 ========== */
    fun init(serverIp: String = DEFAULT_SERVER_IP,
             serverPort: Int = DEFAULT_SERVER_PORT,
             viewModel: MainVM? = null) {
        if (isRunning) return

        this.serverIp = serverIp
        this.serverPort = serverPort
        this.mainViewModel = viewModel
        this.isRunning = true
        this.isManualStop = false
        this.reconnectAttempts = 0

        scope.launch { manageConnection() }
        scope.launch { processSendQueue() }
        LogUtils.i("SocketClient 初始化完成")
    }

    fun stop() {
        isRunning = false
        isManualStop = true
        reconnectAttempts = 0
        scope.coroutineContext.cancelChildren()
        safeCloseSocket()
        sendChannel.close()
        LogUtils.i("SocketClient 已停止")
    }

    fun sendData(data: String) {
        if (!isRunning) {
            LogUtils.w("尝试在未运行状态下发送数据")
            return
        }

        scope.launch {
            try {
                sendChannel.send("$data$MESSAGE_DELIMITER")
                LogUtils.d("数据已加入发送队列: ${data.take(50)}...")
            } catch (e: Exception) {
                LogUtils.e("发送数据到队列失败: ${e.message}")
            }
        }
    }

    /* ========== 核心连接管理 ========== */
    private suspend fun manageConnection() {
        while (isRunning) {
            try {
                // 检查是否需要重连（首次连接或超过30秒无活动）
                if (shouldReconnect()) {
                    socket = createSocket().also {
                        LogUtils.i("已连接到服务器 $serverIp:$serverPort")
                        reconnectAttempts = 0
                        updateActivityTime()
                        _connectionStatus.value = true
                        mainViewModel?.updateConnectionStatus(true)
                    }

                    // 启动接收和心跳协程
                    val receiveJob = scope.launch { receiveData() }
                    val heartbeatJob = scope.launch { sendHeartbeat() }

                    // 等待这两个协程完成（意味着连接断开）
                    joinAll(receiveJob, heartbeatJob)
                } else {
                    delay(1000) // 检查间隔
                }
            } catch (e: Exception) {
                LogUtils.e("连接错误: ${e.message}")
                _connectionStatus.value = false
                mainViewModel?.updateConnectionStatus(false)
                handleReconnect()
            } finally {
                safeCloseSocket()
            }
        }
    }

    private fun shouldReconnect(): Boolean {
        return socket?.isConnected != true ||
                System.currentTimeMillis() - lastActivityTime > MAX_RECONNECT_INTERVAL
    }

    private suspend fun handleReconnect() {
        if (isRunning && !isManualStop) {
            reconnectAttempts++ // 可选：如果仍需计数
            LogUtils.w("将在15秒后尝试重连...")
            delay(RECONNECT_DELAY) // 固定15秒延迟
        }
    }

    private fun calculateReconnectDelay(): Long {
        return minOf(
            RECONNECT_DELAY * (1 shl reconnectAttempts), // 指数退避
            MAX_RECONNECT_INTERVAL
        )
    }

    /* ========== Socket操作 ========== */
    private fun createSocket(): Socket {
        return Socket(serverIp, serverPort).apply {
            soTimeout = SOCKET_TIMEOUT.toInt()
            keepAlive = true
            tcpNoDelay = true
            LogUtils.d("Socket参数: soTimeout=$soTimeout, keepAlive=$keepAlive, tcpNoDelay=$tcpNoDelay")
        }
    }

    private fun safeCloseSocket() {
        try {
            socket?.close()
            LogUtils.i("Socket已安全关闭")
        } catch (e: IOException) {
            LogUtils.e("Socket关闭错误: ${e.message}")
        } finally {
            socket = null
            receiveBuffer.clear()
            _connectionStatus.value = false
        }
    }

    /* ========== 数据传输 ========== */
    private suspend fun sendHeartbeat() {
        while (isRunning && socket?.isConnected == true) {
            try {
                sendData("H")
                LogUtils.v("心跳包已发送")
                updateActivityTime()
                delay(HEARTBEAT_INTERVAL)
            } catch (e: Exception) {
                LogUtils.e("心跳发送错误: ${e.message}")
                break
            }
        }
    }

    private suspend fun processSendQueue() {
        for (message in sendChannel) {
            try {
                if (socket?.isConnected != true) continue
                socket?.getOutputStream()?.let { output ->
                    output.write(message.toByteArray())
                    output.flush()
                    updateActivityTime()
                    LogUtils.d("消息已发送: ${message.trim().take(50)}")
                    delay(1000) // 1秒延迟
                }
            } catch (e: Exception) {
                LogUtils.e("发送错误: ${e.message}")
                safeCloseSocket()
            }
        }
    }

    private suspend fun receiveData() {
        val buffer = ByteArray(BUFFER_SIZE)

        while (isRunning && socket?.isConnected == true) {
            try {
                val inputStream = socket?.getInputStream() ?: break
                val len = try {
                    inputStream.read(buffer)
                } catch (e: SocketTimeoutException) {
                    continue
                } catch (e: Exception) {
                    LogUtils.e("读取异常: ${e.message}")
                    break
                }

                when {
                    len == -1 -> {
                        LogUtils.w("连接已关闭")
                        break
                    }
                    len > 0 -> {
                        val received = String(buffer, 0, len)
                        updateActivityTime()
                        LogUtils.d("收到数据[${len}字节]: ${received.take(100)}")
                        receiveBuffer.append(received)
                        processReceivedMessages()
                    }
                }
            } catch (e: Exception) {
                LogUtils.e("接收异常: ${e.message}")
                break
            }
        }
    }

    /* ========== 业务逻辑 ========== */
    private fun updateActivityTime() {
        lastActivityTime = System.currentTimeMillis()
    }

    private suspend fun processReceivedMessages() {
        if (receiveBuffer.isNotEmpty()) {
            val message = receiveBuffer.toString()
            receiveBuffer.clear()
            if (message.isNotBlank()) {
                handleMessage(message)
            }
        }
    }

    private suspend fun handleMessage(msg: String) {
        LogUtils.i("====== 处理业务消息 ======")
        LogUtils.d("消息内容: ${msg.take(200)}")
        LogUtils.d("当前ID: ${IdStorer.id}")

        try {
            Http.updateNote(IdStorer.id, "", msg) { code ->
                when (PhotoStatus.entries.find { it.code == code.type }) {
                    PhotoStatus.THREE_D_PHOTO -> handle3DPhoto()
                    PhotoStatus.TAKE_PHOTO -> handleTakePhoto(code.range.toString())
                    PhotoStatus.TAKE_TWO_PHOTO -> handleTakeTwoPhoto()
                    PhotoStatus.THREE_D_TWO_PHOTO -> handle3DTwoPhoto()
                    PhotoStatus.CODE_PRINTER -> handleCodePrinter(code.penmaji.toString())
                    null -> LogUtils.w("未知操作类型: ${code.type}")
                }
            }
        } catch (e: Exception) {
            LogUtils.e("消息处理异常: ${e.message}")
        }
    }

    private fun handle3DPhoto() {
        LogUtils.i("执行3D拍照指令")
        UartUtil.onDataSend("{\"cmd\":\"control\",\"dengguang\":{\"sw\":\"K\"}}")
    }

    private fun handleTakePhoto(range: String) {
        LogUtils.i("执行2D拍照移动指令")
        UartUtil.onDataSend(range)
    }

    private fun handleTakeTwoPhoto() {
        LogUtils.i("执行2D拍照完成指令")
        UartUtil.onDataSend("{\"cmd\":\"control\",\"dengguang\":{\"sw\":\"G\"}}")
        mainViewModel?.updateDeviceStatus { it.copy(camera2D = "已拍照") }
    }

    private fun handle3DTwoPhoto() {
        LogUtils.i("执行3D拍照完成指令")
        mainViewModel?.updateDeviceStatus { it.copy(camera3D = "已拍照") }
        UartUtil.onDataSend("{\"cmd\":\"control\",\"dianji\":{\"yd\":\"H\"}}")
    }

    private fun handleCodePrinter(penmaji: String) {
        LogUtils.i("执行喷码器指令")
        UartUtil.onDataSend(penmaji)
    }
}